package com.csx.base;

import com.csx.Context;
import com.csx.base.meta.OdsColumn;
import com.csx.base.meta.OdsIndex;
import com.yh.csx.bsf.core.db.DbConn;
import com.yh.csx.bsf.core.db.DbHelper;
import com.yh.csx.bsf.core.util.ConvertUtils;
import com.yh.csx.bsf.core.util.LogUtils;
import com.yh.csx.bsf.core.util.ThreadUtils;
import lombok.var;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class MysqlUtils {
    public static List<OdsColumn> getTableColumns(String sourceDb, String sourceTable){
        try (DbConn dbConn = Context.StragtegyProvider.getDb(sourceDb)) {
            var rs = dbConn.executeList(
                    "select * from information_schema.columns where table_schema =? and table_name=?",
                    new Object[]{sourceDb, sourceTable});
            List<OdsColumn> columns = new ArrayList<OdsColumn>();
            // 同步表结构
            for (var r : rs) {
                var odsColumn = new OdsColumn();
                odsColumn.setColumnName(ConvertUtils.convert(r.get("COLUMN_NAME"), String.class));
                odsColumn.setOrdinalPosition(Integer.valueOf(ConvertUtils.convert(r.get("ORDINAL_POSITION"), String.class).replaceAll(",", "")));
                odsColumn.setColumnDefault(ConvertUtils.convert(r.get("COLUMN_DEFAULT"), String.class));
                //.setNullable("YES".equals(rs.getString("IS_NULLABLE").toUpperCase()) ? true : false)
                odsColumn.setDataType(ConvertUtils.convert(r.get("DATA_TYPE"), String.class));
                odsColumn.setCharacterMaxmunLength(Long.valueOf(Optional
                        .ofNullable(ConvertUtils.convert(r.get("CHARACTER_MAXIMUM_LENGTH"), String.class)).orElse("0").replaceAll(",", "")));
                odsColumn.setCharacterOctetLength(Long.valueOf(Optional
                        .ofNullable(ConvertUtils.convert(r.get("CHARACTER_OCTET_LENGTH"), String.class)).orElse("0").replaceAll(",", "")));
                odsColumn.setNumericPrecision(ConvertUtils.convert(r.get("NUMERIC_PRECISION"), int.class));
                odsColumn.setNumericScale(ConvertUtils.convert(r.get("NUMERIC_SCALE"), int.class));
                odsColumn.setDatetimePrecision(ConvertUtils.convert(r.get("DATETIME_PRECISION"), int.class));
                odsColumn.setCharacterSetName(ConvertUtils.convert(r.get("CHARACTER_SET_NAME"), String.class));
                odsColumn.setCollationName(ConvertUtils.convert(r.get("COLLATION_NAME"), String.class));
                odsColumn.setColumnType(ConvertUtils.convert(r.get("COLUMN_TYPE"), String.class));
                odsColumn.setColumnKey(ConvertUtils.convert(r.get("COLUMN_KEY"), String.class));
                odsColumn.setExtra(ConvertUtils.convert(r.get("EXTRA"), String.class));
                odsColumn.setComment(ConvertUtils.convert(r.get("COLUMN_COMMENT"), String.class));
                columns.add(odsColumn);
            }
            return columns;
        }
    }


    private static Object _lock = new Object();
    public static List<String> getAllFullNameTables(){
        var stragtegyProvider = Context.StragtegyProvider;
        var result = new ArrayList<String>();
        ThreadUtils.parallelFor("mysql 所有表扫描", Config.getMysqlFullTablesParallelCount(),stragtegyProvider.getDbs(),(db)->{
            try (DbConn dbConn = stragtegyProvider.getDb(db)) {
                if (dbConn != null) {
                    List<Map<String, Object>> rs = dbConn.executeList(
                            "select distinct table_name from information_schema.columns where table_schema =?",
                            new Object[] { db });
                    for (var r : rs) {
                        var table = ConvertUtils.convert(r.get("TABLE_NAME"), String.class);
                        synchronized (_lock) {
                            if(!stragtegyProvider.isMysqlBlackTable(db,table)) {
                                var fullName = stragtegyProvider.fullName(db, table);
                                result.add(fullName);
                            }
                        }
                    }
                } else {
                    LogUtils.error(MysqlUtils.class, Config.ProjectName, "数据源未配置:" + db,new Exception());
                }
            }
        });
        return result;
    }

    public static boolean existsTable(String sourceDb, String sourceTable) {
        String sql = "select table_name from information_schema.TABLES where table_schema='"+sourceDb+"' and table_name='"+sourceTable+"' limit 0,1";
        return DbHelper.get(Context.StragtegyProvider.getDS(sourceDb),(c->{
            return c.executeList(sql,null).size()>0;
        }));
    }

    public static boolean existsIndex(String sourceDb,String sourceTable,String column){
        String sql = "show index from "+sourceDb+"."+sourceTable+" where column_name='"+column+"';";
        return DbHelper.get(Context.StragtegyProvider.getDS(sourceDb),(c->{
            return c.executeList(sql,null).size()>0;
        }));
    }

}
